using UnityEngine;
using System.Collections;
using System.Collections.Generic;

namespace Game.Global.Helper
{
    /// <summary>
    /// 协程辅助类
    /// 如协程关闭同一个UI、协程操作同一个UI后的完成动作等
    /// </summary>
    public static class CoroutineHelper
    {

        static List<ObjHolder> g_listUIObjShowHolder = null;
        //------------------------------------------------
        //--        UI show and hide
        //------------------------------------------------
        //--管理部分

        /// <summary>
        /// 尝试一个协程完成后的退出动作，如果多个协程正在进行，则将只有最后一个协程会执行此动作
        /// </summary>
        /// <param name="uiRect">User interface rect.</param>
        /// <param name="cbIfExitSucc">当协程是最后一个在操作UI的时候，则会执行此回调</param>
        /// <param name="deleteObjHolder">是否要清空掉对应的管理类，如果该ui或物体是不被删除，而且经常被协程使用，则应该设置为false</param>
        public static void TryEndCoroutineFor(Transform uiRect, CallbackFunc cbIfExitSucc, bool deleteObjHolder = false)
        {
            //--在管理列表找到这个UI
            ObjHolder objHodler = FindObjHolder(uiRect, false); //不会产生新的管理类

#if UNITY_EDITOR
            if (objHodler == null)
            {
                Debug.LogError("调用前确保该协程或其他协程有先占用此物体:" + uiRect.name);
                return;
            }
#endif

            //--减少计数
            objHodler.SubObjUseCount();

            //--探寻是否可关闭
            if (objHodler.IsObjCanClose())
            {
                //--真正关闭：
                cbIfExitSucc();

                if (deleteObjHolder)
                {
                    //--删除这个管理类：
                    g_listUIObjShowHolder.Remove(objHodler);
                }
            }
        }

        /// <summary>
        /// 标记某个物体将被协程占用，对于互斥动作将排斥其他同个协程的使用.
        /// <para>推荐直接使用管理器进行管理</para>
        /// </summary>
        /// <param name="trans"></param>
        [System.Obsolete("请直接使用Holder进行管理")]
        public static void StartCoroutineUsing(Transform trans)
        {
            //在管理列表中找到这个ui; 
            ObjHolder objHodler = FindObjHolder(trans, true); //未找到，则产生一个管理类，并加入管理列表：

            //--对管理类进行+1
            objHodler.AddObjUseCount();

        }

        //todo rectTransform -> Transform
        /// <summary>
        /// 【不推荐】探查这个UI是否显示ing，在多协程使用同一个UI时可以有效管理
        /// </summary>
        [System.Obsolete("请直接使用Holder进行管理")]
        public static bool IsUIUsing(Transform uiRect)
        {
            ObjHolder objHolder = FindObjHolder(uiRect, false);
            if (objHolder == null)
            {
                return false;
            }
            else
            {
                return objHolder.IsObjUsing();
            }
        }

        /// <summary>
        /// 如果这个物体之前被设定过数据，则获得对应的ObjHolder的数据（具体数据由调用方决定）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="trans"></param>
        /// <returns></returns>
        [System.Obsolete("请直接使用Holder进行管理")]
        public static T GetHolderData<T>(Transform trans)
        {
            ObjHolder holder = FindObjHolder(trans, false);
            if (holder == null)
            {
                return default(T);
            }
            else
            {
                return (T)(holder.otherData);
            }
        }

        /// <summary>
        /// 强行对一个物体设置挂载的数据，不要求UI被占用（具体数据由调用方决定）
        /// </summary>
        /// <param name="trans"></param>
        /// <param name="objData"></param>
        [System.Obsolete("请直接使用Holder进行管理")]
        public static void SetHolderData(Transform trans, object objData)
        {
            ObjHolder holder = FindObjHolder(trans, true);

            holder.otherData = objData;
        }

        /// <summary>
        /// 寻找对应的管理器
        /// </summary>
        /// <param name="uiRect"></param>
        /// <param name="createIfNull"></param>
        /// <returns></returns>
        public static ObjHolder FindObjHolder(Transform uiRect, bool createIfNull)
        {
            if (g_listUIObjShowHolder == null)
            {
                g_listUIObjShowHolder = new List<ObjHolder>();
            }

            ObjHolder objHolder = g_listUIObjShowHolder.Find((holder) => { return holder.objRectTransform == uiRect; });

            if (objHolder == null && createIfNull)
            {
                objHolder = new ObjHolder() { objRectTransform = uiRect };
                g_listUIObjShowHolder.Add(objHolder);
            }

            return objHolder;
        }

        /// <summary>
        /// 删掉该管理器
        /// </summary>
        /// <param name="objHolder"></param>
        public static void RemoveObjHolder(ObjHolder objHolder)
        {
            g_listUIObjShowHolder.Remove(objHolder);
        }
        //--         End of UI show & hide


        //UI物体的显示管理
        public class ObjHolder
        {
            /// <summary>
            /// 对UI或Obj的RectTransform引用
            /// </summary>
            public Transform objRectTransform;

            /// <summary>
            /// 这个UI被显示次数（为0则为无显示）
            /// </summary>
            int objShowCount = 0;

            /// <summary>
            /// 其他用于附属到UI物体上的数据
            /// </summary>
            public object otherData = null;

            //--增加被显示的次数
            public void AddObjUseCount()
            {
                objShowCount++;
            }

            //--减少被显示的次数
            public void SubObjUseCount()
            {
                objShowCount--;
            }

            public bool IsObjCanClose()
            {
                return objShowCount <= 0;
            }

            public bool IsObjUsing()
            {
                return objShowCount > 0;
            }

            /// <summary>
            /// 暂不使用此方法
            /// </summary>
            /// <param name="cbIfExitSucc"></param>
            [System.Obsolete("暂不使用此方法")]
            public void TryEndWhenNoUsing(CallbackFunc cbIfExitSucc)
            {

                //--减少计数
                SubObjUseCount();

                //--探寻是否可关闭
                if (IsObjCanClose())
                {
                    //--真正关闭：
                    cbIfExitSucc();
                }
            }
        }
    }
}